package entities;

import com.haxepunk.Entity;
import com.haxepunk.graphics.Spritemap;
import com.haxepunk.tmx.TmxObject;
import flash.geom.Point;
import com.haxepunk.utils.Input;
import com.haxepunk.utils.Key;
import com.haxepunk.HXP;
import scenes.GameScene;

enum StateTokiJuju
{
	IDLE; RUN; JUMP; DUCKING; END;
}

/**
 * ...
 * @author Marcelo Ruben Guardia
 */
class TokiJuju extends Entity
{
	private var spTokiJuju:Spritemap;
	private var state:StateTokiJuju;
	private var v:Point;
	private var vRun:Float;
	private var vJump:Float;
	private var g:Float;
	private var canChangeG:Bool;
	private var outOfCamera:Bool;

	public function new(obj:TmxObject) 
	{
		super(obj.x, obj.y);
		state = IDLE;// RUN;
		spTokiJuju = new Spritemap(GC.IMG_toki_juju, 64, 64);
		spTokiJuju.add(IDLE.getName(), [14], 0, false);
		spTokiJuju.add(RUN.getName(), [0, 1, 2, 3, 4, 5], 15, true);
		spTokiJuju.add(JUMP.getName(), [13, 14], 8, false);
		spTokiJuju.add(DUCKING.getName(), [7, 8, 9, 10, 11, 12], 15, true);
		spTokiJuju.add(END.getName(), [81], 0, false);
		
		spTokiJuju.play(state.getName());
		graphic = spTokiJuju;
		v = new Point();// 5, 0);
		vRun = 10;
		vJump = 12;
		g = GC.G;
		canChangeG = false;
		outOfCamera = false;
		
		//v.x = 5;
		//v.y = 0;
		type = "toki_juju";
		spTokiJuju.centerOrigin();
		
		
		Input.define("triggerG", [Key.SPACE]);
		Input.define("up", [Key.UP, Key.W]);
		Input.define("down", [Key.DOWN, Key.S]);
		Input.define("left", [Key.LEFT, Key.A]);
	}
	
	override public function update():Void
	{
		super.update();
		
	 moveBy(v.x, v.y,"solid");
		
		HXP.setCamera(x - HXP.halfWidth, 0);
		
		(g > 0) ? UpdateNormal() : UpdateInvertido();
		
		// si toca alguna plataforma arriba o abajo, se habilita el cambio de Gravedad
		canChangeG = (collide("solid", x, y + 1) != null || collide("solid", x, y - 1) != null);
		
		// si sale de la vista de camara, se indica true para volver a iniciar el nivel o checkpoint
		outOfCamera = ((y < HXP.camera.y - 300) || (y > HXP.camera.y + HXP.height + 300));

		if (canChangeG && ChangeG())
		{
			(g > 0) ? v.y = -10 : v.y = 10;
			g = -g;			
			spTokiJuju.scaleY *= -1;
		}		
		
		if (outOfCamera || collide("death", x, y) != null)
		{
			HXP.scene = new GameScene();
		}
		
		if (collide("exitLevel", x, y) != null)
		{
			ChangeState(END);
		}
		if (Input.released("left"))		{
			v.x *= -1;
		}
	}
	
	public function UpdateNormal():Void
 {		
		switch(state)
		{
			case IDLE:
				setHitbox(22, 45, 11, 12);
				v.y += g * HXP.elapsed;
				if (ChocaraPisoNormal())
				{
					v = new Point(vRun, 0);
					ChangeState(RUN);
				}
				
			case RUN:
				setHitbox(22, 45, 11, 12);
				if (SaltarNormal())
					v = new Point(v.x, -vJump);
				
				if (!ChocaraPisoNormal())
					ChangeState(JUMP);
				
				if (DuckNormal())
					ChangeState(DUCKING);
				
			case JUMP:
				setHitbox(22, 42, 11, 9);
				v.y += g * HXP.elapsed;
				if (ChocaraPisoNormal())
				{
					v = new Point(vRun, 0);
					ChangeState(RUN);
				}
				
			case DUCKING:
				setHitbox(40, 30, 20, -3);
				if (SaltarNormal())
				{
					v.y = -vJump;
					ChangeState(JUMP);
				}
					
				if (!ChocaraPisoNormal())
					ChangeState(JUMP);
								
				if (!DuckNormal())
					ChangeState(RUN);
			
			case END:
				setHitbox(22, 45, 11, 12);
				v.x = 0; //v.y = 0;	
		}
	}
	
	public function UpdateInvertido():Void
	{
		switch(state)
		{
			case IDLE:
				setHitbox(22, 45, 11, 32);
				v.y += g * HXP.elapsed;
				if (ChocaraPisoInvertido())
				{
					v = new Point(vRun, 0);
					ChangeState(RUN);
				}
				
			case RUN:
				setHitbox(22,45,11,32);
				if (SaltarInvertido())
					v = new Point(v.x, vJump);
				
				if (!ChocaraPisoInvertido())
					ChangeState(JUMP);
				
				if (DuckInvertido())
					ChangeState(DUCKING);
				
			case JUMP:
				setHitbox(22, 42, 11, 32);
				v.y += g * HXP.elapsed;
				if (ChocaraPisoInvertido())
				{
					v = new Point(vRun, 0);
					ChangeState(RUN);
				}
				
			case DUCKING:
				setHitbox(40,30,20,32);
				if (SaltarInvertido())
				{
					v.y = vJump;
					ChangeState(JUMP);
				}
					
				if (!ChocaraPisoInvertido())
					ChangeState(JUMP);
				
				if (!DuckInvertido())
					ChangeState(RUN);
			
			case END:
				setHitbox(22, 45, 11, 32);
				v.x = 0; //v.y = 0;
		}
	}
	
	public function ChangeG():Bool	{															return Input.check("triggerG");	}
	public function SaltarNormal():Bool	{										return Input.check("up");	}
	public function SaltarInvertido():Bool	{							return Input.check("down");	}
	public function DuckNormal():Bool	{												return Input.check("down");	}
	public function DuckInvertido():Bool	{									return Input.check("up");	}
	public function ChocaraPisoNormal():Bool	{					return (collide("solid", x, y + 1) != null);	}
	public function ChocaraPisoInvertido():Bool	{		return (collide("solid", x, y - 1) != null);	}
	
	
	
	public function ChangeState(newState:StateTokiJuju)
	{
		state = newState;
		spTokiJuju.play(state.getName());
	}
	
	
}